package org.fuys.etp.core.metrics.impl.trend;

import org.fuys.etp.core.metrics.EtpMetricsHandler;
import org.fuys.etp.core.model.type.EtpTaskTrendTypeEnum;
import org.fuys.etp.core.model.type.EtpTypeEnum;
import org.fuys.etp.core.model.vo.TpConfigVO;
import org.fuys.etp.core.model.vo.TpStatusVO;
import org.fuys.etp.core.pool.EtpThreadPoolExecutor;
import org.fuys.etp.core.pool.algorithm.PIDController;
import org.fuys.etp.core.pool.algorithm.TaskCountPredictor;
import org.springframework.stereotype.Component;

import java.util.concurrent.ThreadPoolExecutor;

/**
 * @projectName: fuys-etp-final
 * @package: org.fuys.etp.core.metrics.impl.trend
 * @className: AdaptiveTrendHandler
 * @author: WangJing
 * @description: 自适应线程池任务趋势处理器
 * @date: 2025/2/18 22:31
 * @version: 1.0
 */
@Component("adaptiveTrendHandler")
public class AdaptiveTrendHandler implements EtpMetricsHandler {
    @Override
    public void metricsCollect(ThreadPoolExecutor executor, TpStatusVO result) {
        if(executor instanceof EtpThreadPoolExecutor){
            EtpThreadPoolExecutor etp = (EtpThreadPoolExecutor) executor;
            if (EtpTypeEnum.ADAPTIVE_THREAD_POOLS_EXECUTOR.type().equals(etp.getType())) {
                final PIDController pidController = etp.getPidController();
                final TaskCountPredictor taskPredictor = etp.getTaskPredictor();
                if(pidController!=null && taskPredictor!=null){
                    Double queueUsage = result.getQueueUsage();
                    if(queueUsage == null){
                        final int size = etp.getQueue().size();
                        final int remainingCapacity = etp.getQueue().remainingCapacity();
                        queueUsage = (double) (size - remainingCapacity) / (double) (size);
                    }
                    final TpConfigVO actualConfig = etp.getActualConfig();
                    final double calculate = pidController.calculate(queueUsage);
                    final double predict = taskPredictor.predict();
                    final long taskCount = etp.getTaskCount();
                    if(calculate>0 && predict >= taskCount * actualConfig.getDynamicConfig().getWindowsChangeTrend()){
                        result.setTaskTrend(EtpTaskTrendTypeEnum.INCREASE.getType());
                    }else if(calculate<0 && predict <= -taskCount * actualConfig.getDynamicConfig().getWindowsChangeTrend()){
                        result.setTaskTrend(EtpTaskTrendTypeEnum.DECREASE.getType());
                    }else{
                        result.setTaskTrend(EtpTaskTrendTypeEnum.NONE.getType());
                    }
                    result.setPidResult(calculate);
                    result.setPredicted(predict);
                    return;
                }
            }
        }
        result.setTaskTrend(EtpTaskTrendTypeEnum.UNABLE.getType());
    }
}
